package edu.cicese.alz.util;

import edu.cicese.alz.Subject;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.util.Calendar;
import java.util.List;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 5/06/12
 * Time: 01:57 PM
 */
public class Utilities {

	private static String dsvSep = ";";

	//! Deletes a directory and all its content
//	@SuppressWarnings({"ResultOfMethodCallIgnored"})
	public static boolean deleteDirectory(String path) {
		boolean successful = true;
		try {
//			System.out.println("Deleting " + path);
			File dir = new File(path);
			if (dir.exists()) {
				File[] files = dir.listFiles();
				if (files != null) {
					for (File file : files) {
						if (file.isDirectory()) {
							successful = deleteDirectory(file.getCanonicalPath());
						}
						if (!file.delete()) {
							System.out.println("Couldn't delete " + file);
							successful = false;
						}
					}
				}
				if (!dir.delete()) {
					System.out.println("Couldn't delete " + dir);
					successful = false;
				}
			}
			else {
//				System.out.println(dir + " doesn't exists.");
			}
		}
		catch (IOException e) { e.printStackTrace(); successful = false; }
		catch (NullPointerException e) { e.printStackTrace(); successful = false; }
		return successful;
	}

	public static boolean moveFile(String origin, String destination) {
		return new File(origin).renameTo(new File(destination));
	}

	public static String getSystemSeparator() {
		return File.separator;
	}

	public static String getInfileDir(int userID) {
		return PropertyUtil.getProperty(PropertyUtil.HOME_DIR) + getSystemSeparator() + userID + getSystemSeparator() + "infiles";
	}

	public static String getFieldSeparator() {
		return dsvSep;
	}

	public static void checkDirs(List<Subject> subjects) {
		String systemSeparator = getSystemSeparator();
		String usersDir = PropertyUtil.getProperty(PropertyUtil.HOME_DIR) + systemSeparator + "users" + systemSeparator;
		String userDir;
		for (Subject subject : subjects) {
			userDir = usersDir + subject.getUserID();
			new File(userDir + systemSeparator + "infiles").mkdirs();
			new File(userDir + systemSeparator + "charts").mkdirs();
			new File(userDir + systemSeparator + "json").mkdirs();
		}
	}

	public static void saveDataFile(String filename, String row) {
		try {
			PrintWriter pw = new PrintWriter(new FileWriter(filename, true));
			pw.print(row);
			pw.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void saveToFile(Object object, String folder, String filename) {
		try {
			File file = new File(folder);
			file.mkdirs();
			ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(new File(folder + filename)));
			stream.writeObject(object);
			stream.close();
		}
		catch (IOException e) { e.printStackTrace(); }
	}

	public static int getLineCount(File file) {
		InputStream is = null;
		try {
			is = new BufferedInputStream(new FileInputStream(file));
			byte[] c = new byte[1024];
			int count = 0;
			int readChars = 0;
			while ((readChars = is.read(c)) != -1) {
				for (int i = 0; i < readChars; ++i) {
					if (c[i] == '\n')
						++count;
				}
			}
			return count;
		} catch (IOException e) {
			e.printStackTrace();
			return 0;
		} finally {
			if (is!= null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static String getLastLine(File file) {
		RandomAccessFile fileHandler = null;
		try {
			fileHandler = new RandomAccessFile(file, "r");
			long fileLength = file.length() - 1;
			StringBuilder sb = new StringBuilder();

			for (long filePointer = fileLength; filePointer != -1; filePointer--) {
				fileHandler.seek(filePointer);
				int readByte = fileHandler.readByte();

				if (readByte == 0xA) {
					if (filePointer == fileLength) {
						continue;
					} else {
						break;
					}
				} else if (readByte == 0xD) {
					if (filePointer == fileLength - 1) {
						continue;
					} else {
						break;
					}
				}

				sb.append((char) readByte);
			}

			String lastLine = sb.reverse().toString();
			return lastLine;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} finally {
			if (fileHandler != null) {
				try {
					fileHandler.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static String getFirstLine(File file) {
		RandomAccessFile fileHandler = null;
		try {
			fileHandler = new RandomAccessFile(file, "rw");
			String firstLine = fileHandler.readLine();
			fileHandler.close();
			return firstLine;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} finally {
			if (fileHandler != null) {
				try {
					fileHandler.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void printLog(String msg) {
		Calendar calendar = Calendar.getInstance();
		System.out.println("[" +
				addZeros(calendar.get(Calendar.HOUR_OF_DAY), 2) + ":" +
				addZeros(calendar.get(Calendar.MINUTE), 2) + ":" +
				addZeros(calendar.get(Calendar.SECOND), 2) + "] " + msg);
	}

	public static String addZeros(int value, int length) {
		String valueWithZeros = String.valueOf(value);
		while (valueWithZeros.length() < length) {
			valueWithZeros = "0" + valueWithZeros;
		}
		return valueWithZeros;
	}
}
